#!/bin/bash
PWD="`pwd`"
tool_chains_dir=`pwd`/../toolchains
tool_chains_gcc_dir=gcc-linaro-5.3-2016.02-x86_64_aarch64-elf

app_tool_chains_gcc=$tool_chains_dir/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
tool_chains_name=gcc-linaro-5.3-2016.02-x86_64_aarch64-elf.tar.bz2
config_dir=`pwd`/arch/arm64/configs/qemu_defconfig
config_name=.config

if [ -z $ARCH ]; then
	ARCH="arm64"
fi

if [ -z $MACH ]; then
	MACH="qemu"
fi

if [ $ARCH == "arm64" ]; then
	CROSS_COMPILE=$tool_chains_dir/$tool_chains_gcc_dir/bin/aarch64-elf-
elif [ $ARCH == "riscv64" ]; then
	CROSS_COMPILE=riscv64-linux-gnu-
fi

function first_complie(){
    if [ -f $config_name ];then
        return
    fi

    cp $config_dir $config_name
}

function first_toolchain(){
    if [ -d $tool_chains_dir/$tool_chains_gcc_dir ];then
        return
    fi

    cd $tool_chains_dir

    echo "merge tool chain file..."
    cat xa* > $tool_chains_name

    echo "Unpack the tool chain package..."
    tar xf $tool_chains_name

    cd -
}


function mkcpio()
{
	# mk cpio image
	cd ./rootfs && find . -not -name . | cpio -o -H newc --quiet > ../rootfs.cpio && cd ..
	# flush the asm file
	cp cpio_img.S fs/romfs/cpio_img.S
}

function distclean()
{
	make ARCH=$ARCH distclean
	make ARCH=$ARCH clean
}

#
# 清除编译生成的文件
#
function clean()
{
    make ARCH=$ARCH clean
}

function defconfig()
{
	make ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE "$MACH"_defconfig
}

#
# 生成clangd所用的compile_commands.json文件
# 实用于vscode上的clangd插件实现代码提示、跳转和补全，方便开发
#
function get_cc_jsonfile
{
	clean
	defconfig
	if [ $ARCH == "arm64" ]; then
		bear make ARCH=arm64 EXTRA_CFLAGS="-g -D__LINUX_ARM_ARCH__=8 -DCONFIG_QEMU=1" CROSS_COMPILE=$CROSS_COMPILE Image
	elif [ $ARCH == "riscv64" ]; then
		bear make ARCH=riscv64 EXTRA_CFLAGS="-g" CROSS_COMPILE=$CROSS_COMPILE \
		Image dtbs;	
	fi
}

function run()
{
	if [ $ARCH == "arm64" ]; then
		sudo -S qemu-system-aarch64 -display none \
		-machine virt -cpu cortex-a53 \
		-smp 4 -m 1024 -serial stdio -kernel arch/arm64/boot/Image \
		-drive file=./dim-sum.img,if=none,id=blk \
		-device virtio-blk-device,drive=blk \
		-device virtio-net-device,netdev=network0,mac=52:54:00:4a:1e:d4 \
		-netdev tap,id=network0,ifname=tap0 \
		--append "earlyprintk console=ttyAMA0 \
		root=/dev/vda rootfstype=ext3 \
		init=/bin/ash rw ip=10.0.0.10::10.0.0.1:255.255.255.0:::off"
	elif [ $ARCH == "riscv64" ]; then
		sudo qemu-system-riscv64 -display none \
		-machine virt -smp 4 -m 3072 -serial stdio \
		-kernel arch/riscv64/boot/Image \
		-drive file=./dim-sum.img,if=none,id=blk \
		-device virtio-blk-device,drive=blk \
		-device virtio-net-device,netdev=network0,mac=52:54:00:4a:1e:d4 \
		-netdev tap,id=network0,ifname=tap0 \
		--append "earlyprintk console=ttyAMA0 \
		root=/dev/vda rootfstype=ext3 \
		init=/bin/ash rw ip=10.0.0.10::10.0.0.1:255.255.255.0:::off"
	fi
}


function compile()
{
	if [ $ARCH == "arm64" ]; then
		make ARCH=arm64 EXTRA_CFLAGS="-g -D__LINUX_ARM_ARCH__=8 -DCONFIG_QEMU=1" CROSS_COMPILE=$CROSS_COMPILE Image dtbs
	elif [ $ARCH == "riscv64" ]; then
		make ARCH=riscv64 EXTRA_CFLAGS="-g" CROSS_COMPILE=$CROSS_COMPILE \
		Image dtbs;	
	fi
}

function cp_uapp()
{
	cp uapp.elf ../../../../rootfs/uapp.elf
}

function newuapp()
{
	if [ $ARCH == "arm64" ]; then
		app_tool_chains_gcc=$tool_chains_dir/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
		cd `dirname $0`/usr/test/$ARCH/uapp
		make CROSS_COMPILE=$app_tool_chains_gcc clean
		make CROSS_COMPILE=$app_tool_chains_gcc
		cp uapp.elf ../../../../rootfs/uapp.elf
	elif [ $ARCH == "riscv64" ]; then
		app_tool_chains_gcc=$CROSS_COMPILE
		cd `dirname $0`/usr/test/$ARCH/uapp
		make CROSS_COMPILE=$app_tool_chains_gcc clean
		make CROSS_COMPILE=$app_tool_chains_gcc
		cp uapp.elf ../../../../rootfs/uapp.elf
	fi

}

function uapp()
{
	newuapp
}

function all()
{
	mkcpio && compile && run $* && exit
}

function usage()
{
	echo "请使用合适的参数"
}

#
# 将字符串转换为函数，并调用函数
#
function call_sub_cmd()
{
	#
	# 通过第一个参数，获得想要调用的函数名
	# 例如 check 函数
	#
	func=$1
	#
	# 函数名不支持”-“，因此将参数中的”-“转换为”_“
	#
	func=${func//-/_}
	#
	# 从参数列表中移除第一个参数，例如 check，将剩余的参数传给函数
	#
	shift 1
	eval "$func $*"
}


#
# 主函数
#
function main()
{
	#
	# 如果没有任何参数，默认调用all函数
	#
	if [ $# -eq 0 ]; then
		all
		exit 0
	fi
	
	#
	# 带参数运行，看看相应的函数是否存在
	#
	SUB_CMD=$1
	type ${SUB_CMD//-/_} > /dev/null 2>&1
	#
	# 要调用的子函数不存在，说明用法错误
	#
	if [ $? -ne 0 ]; then
		usage
		exit
	else
		#
		# 要调用的子函数存在，执行子函数
		#
		shift 1;
		call_sub_cmd $SUB_CMD $*
		exit $?
	fi

	usage
}

#
# 调用主函数
#
main $*